package com.matrix.app.mvc.project.workitem;

import com.matrix.app.flux.project.stage.data.StagePo;
import com.matrix.app.flux.project.stage.repository.StageRepository;
import com.matrix.framework.core.common.global.IOptionService;
import com.matrix.framework.core.common.global.Options;
import com.matrix.framework.lowcode.enums.EventLocation;
import com.matrix.framework.lowcode.eventintf.annotation.ExtendEvent;
import com.matrix.framework.lowcode.eventintf.event.AfterQueryEvent;
import com.matrix.framework.lowcode.eventintf.event.BeforeEditEvent;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Mono;
import reactor.core.scheduler.Schedulers;

import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * Copyright © 海平面工作室 版权所有
 *
 * @Author: Leo
 * @Create: 2025/6/8 16:25
 * @Since 1.0
 */
@Service
public class WorkItemService implements IOptionService, AfterQueryEvent, BeforeEditEvent {


    private final WorkItemRepository workItemRepository;

    private final StageRepository stageRepository;

    public WorkItemService(WorkItemRepository repository, StageRepository stageRepository) {
        this.workItemRepository = repository;
        this.stageRepository = stageRepository;
    }

    @Override
    public Mono<List<Options>> getOptions(Map<String, String> filter) {
        Mono<List<WorkItemPo>> pos = Mono.fromCallable(workItemRepository::findAll);

        Mono<List<Options>> options;
        if (filter != null) {
            options = pos.map(workItems -> workItems.stream()
                    .filter(workItem -> workItem.getStageId().toString().equals(filter.get("stage_id")))
                    .map(p -> new Options(p.getName(), p.getId() + ""))
                    .toList());
        } else {
            options = pos.map(workItems -> workItems.stream()
                    .map(p -> new Options(p.getName(), p.getId() + ""))
                    .toList());
        }

        return options;
    }


    @Override
    @ExtendEvent(tableName = "project_work_progress", eventLocation = EventLocation.AFTER_QUERY, description = "项目进度列表查询后事件, 将阶段id转换为阶段名称,将工作分解id转换为名称供表格显示")
    public Mono<Map<String, Object>> doAfterQuery(Map<String, Object> result) {
        return Mono.just(result)
                .publishOn(Schedulers.boundedElastic())
                .flatMap(d -> {
                    if (d.containsKey("items")) {
                        List<Map<String, Object>> items = (List<Map<String, Object>>) d.get("items");
                        for (Map<String, Object> item : items) {
                            if (item.containsKey("stage_id")) {
                                Long stageId = (Long) item.remove("stage_id");
                                if (stageId != null) {
                                    Mono<StagePo> workItemPo = stageRepository.findById(stageId);
                                    // 取出Mono中的值并赋值给stage_id
                                    StagePo po = workItemPo.block();
                                    item.put("stage_id", po.getName());
                                }
                            }
                            if (item.containsKey("work_item_id")) {
                                Long workItemId = (Long) item.remove("work_item_id");
                                if (workItemId != null) {
                                    Optional<WorkItemPo> workItemPo = workItemRepository.findById(workItemId);
                                    // 取出Mono中的值并赋值给stage_id
                                    WorkItemPo po = workItemPo.get();
                                    item.put("work_item_id", po.getName());
                                }
                            }

                        }
                    }
                    return Mono.just(d);
                });
    }

    @Override
    @ExtendEvent(tableName = "project_work_progress", eventLocation = EventLocation.BEFORE_EDIT, description = "项目进度编辑前事件, 将阶段id和项目分解的id转换为对应的名称")
    public Mono<Map<String, Object>> doBeforeEdit(Map<String, Object> data) {
        return Mono.just(data)
                .publishOn(Schedulers.boundedElastic())
                .map(d -> {
                    Object stageId = data.remove("stage_id");
                    if (stageId != null) {
                        Mono<StagePo> po = stageRepository.findById((Long) stageId);
                        StagePo stagePo = po.block();
                        if (stagePo != null) {
                            data.put("stage_id", stagePo.getName());
                        }
                    }
                    Object workItemId = data.remove("work_item_id");
                    if (workItemId != null) {
                        Optional<WorkItemPo> workItemPo = workItemRepository.findById((Long) workItemId);
                        WorkItemPo po = workItemPo.get();
                        data.put("work_item_id", po.getName());
                    }
                    return d;
                });

    }
}
